/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE
 * file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file
 * to You under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the
 * License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
 * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations under the License.
 */

package com.swak.monitor.dubbo.web;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import org.apache.dubbo.metadata.definition.model.FullServiceDefinition;
import org.apache.dubbo.metadata.report.identifier.MetadataIdentifier;
import org.springframework.beans.factory.annotation.Autowired;

import com.swak.annotation.Get;
import com.swak.annotation.RestApi;
import com.swak.entity.Page;
import com.swak.entity.Parameters;
import com.swak.monitor.dubbo.model.domain.Consumer;
import com.swak.monitor.dubbo.model.domain.Provider;
import com.swak.monitor.dubbo.model.dto.ServiceDTO;
import com.swak.monitor.dubbo.model.dto.ServiceDetailDTO;
import com.swak.monitor.dubbo.service.ConsumerService;
import com.swak.monitor.dubbo.service.ProviderService;
import com.swak.monitor.dubbo.utils.Constants;
import com.swak.monitor.dubbo.utils.Tool;
import com.swak.utils.JsonMapper;

@RestApi(value = "DubboServiceApi", path = "/api/monitor/:env")
public class ServiceApi {

    @Autowired
    private ProviderService providerService;
    @Autowired
    private ConsumerService consumerService;

    @Get("/service")
    public Page<ServiceDTO> searchService(String pattern, String filter, String env, Parameters param) {
        final Set<ServiceDTO> serviceDTOS = providerService.getServiceDTOS(pattern, filter, env);
        final List<ServiceDTO> content = serviceDTOS.stream().skip((param.getPageIndex() - 1) * param.getPageSize())
            .limit(param.getPageSize()).collect(Collectors.toList());
        param.setRecordCount(serviceDTOS.size());
        return new Page<>(param, content);
    }

    @Get("/service/:service")
    public ServiceDetailDTO serviceDetail(String service, String env) {
        service = service.replace(Constants.ANY_VALUE, Constants.PATH_SEPARATOR);
        String group = Tool.getGroup(service);
        String version = Tool.getVersion(service);
        String interfaze = Tool.getInterface(service);
        List<Provider> providers = providerService.findByService(service);

        List<Consumer> consumers = consumerService.findByService(service);

        String application = null;
        if (providers != null && providers.size() > 0) {
            application = providers.get(0).getApplication();
        }
        MetadataIdentifier identifier =
            new MetadataIdentifier(interfaze, version, group, Constants.PROVIDER_SIDE, application);
        String metadata = providerService.getProviderMetaData(identifier);
        ServiceDetailDTO serviceDetailDTO = new ServiceDetailDTO();
        serviceDetailDTO.setConsumers(consumers);
        serviceDetailDTO.setProviders(providers);
        if (metadata != null) {
            FullServiceDefinition serviceDefinition = JsonMapper.fromJson(metadata, FullServiceDefinition.class);
            serviceDetailDTO.setMetadata(serviceDefinition);
        }
        serviceDetailDTO.setConsumers(consumers);
        serviceDetailDTO.setProviders(providers);
        serviceDetailDTO.setService(service);
        serviceDetailDTO.setApplication(application);
        return serviceDetailDTO;
    }

    @Get("/services")
    public Set<String> allServices(String env) {
        return new HashSet<>(providerService.findServices());
    }

    @Get("/applications")
    public Set<String> allApplications(String env) {
        return providerService.findApplications();
    }
}
